home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 4 / QRZ Ham Radio Callsign Database - Volume 4.iso / files / tcpip / amiga / asrc29p.lha / nrcmd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-29  |  23.2 KB  |  1,029 lines

  1. /* net/rom user command processing
  2.  * Copyright 1989 by Daniel M. Frank, W9NK.  Permission granted for
  3.  * non-commercial distribution only.
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <ctype.h>
  8. #include "global.h"
  9. #include "mbuf.h"
  10. #include "ax25.h"
  11. #include "mailbox.h"
  12. #include "netrom.h"
  13. #include "nr4.h"
  14. #include "timer.h"
  15. #include "iface.h"
  16. #include "lapb.h"
  17. #include "cmdparse.h"
  18. #include "session.h"
  19. #include "socket.h"
  20. #include "commands.h"
  21. #include "config.h"
  22.  
  23. #ifdef    MAILBOX
  24. static int Nrsocket = -1;
  25. #endif
  26.  
  27. static int Nr_autorec = 0;
  28.  
  29. char Nr4user[AXALEN];
  30.  
  31. char *Nr4states[] = {
  32.     "Disconnected",
  33.     "Conn Pending",
  34.     "Connected",
  35.     "Disc Pending",
  36.     "Listening"
  37. } ;
  38.  
  39. char *Nr4reasons[] = {
  40.     "Normal",
  41.     "By Peer",
  42.     "Timeout",
  43.     "Reset",
  44.     "Refused"
  45. } ;
  46.  
  47. static int dobcnodes __ARGS((int argc,char *argv[],void *p));
  48. static int dointerface __ARGS((int argc,char *argv[],void *p));
  49. static int donfadd __ARGS((int argc,char *argv[],void *p));
  50. static int donfdrop __ARGS((int argc,char *argv[],void *p));
  51. static int donfdump __ARGS((void));
  52. static int donfmode __ARGS((int argc,char *argv[],void *p));
  53. static int donodefilter __ARGS((int argc,char *argv[],void *p));
  54. static void donodetick __ARGS((void));
  55. static int donodetimer __ARGS((int argc,char *argv[],void *p));
  56. static int donracktime __ARGS((int argc,char *argv[],void *p));
  57. static int donrchoketime __ARGS((int argc,char *argv[],void *p));
  58. static int donrconnect __ARGS((int argc,char *argv[],void *p));
  59. static int donrirtt __ARGS((int argc,char *argv[],void *p));
  60. static int donrkick __ARGS((int argc,char *argv[],void *p));
  61. static int dorouteadd __ARGS((int argc,char *argv[],void *p));
  62. static int doroutedrop __ARGS((int argc,char *argv[],void *p));
  63. static int donrqlimit __ARGS((int argc,char *argv[],void *p));
  64. static int donrreset __ARGS((int argc,char *argv[],void *p));
  65. static int donrretries __ARGS((int argc,char *argv[],void *p));
  66. static int donrroute __ARGS((int argc,char *argv[],void *p));
  67. static int donrstatus __ARGS((int argc,char *argv[],void *p));
  68. static int donrttl __ARGS((int argc,char *argv[],void *p));
  69. static int donrtype __ARGS((int argc,char *argv[],void *p));
  70. static int donruser __ARGS((int argc,char *argv[],void *p));
  71. static int donrverbose __ARGS((int argc,char *argv[],void *p));
  72. static int donrautorec __ARGS((int argc,char *argv[],void *p));
  73. static int donrwindow __ARGS((int argc,char *argv[],void *p));
  74. static void doobsotick __ARGS((void));
  75. static int doobsotimer __ARGS((int argc,char *argv[],void *p));
  76.  
  77. static struct cmds Nrcmds[] = {
  78.     "acktime",    donracktime,    0, 0,    NULLCHAR,
  79.     "autorec",    donrautorec,    0, 0,    NULLCHAR,
  80.     "bcnodes",    dobcnodes,    0, 2,    "netrom bcnodes <interface>",
  81.     "connect",    donrconnect, 1024, 2,    "netrom connect <node>",
  82.     "choketime",    donrchoketime,    0, 0,    NULLCHAR,
  83.     "interface",    dointerface,    0, 4,
  84.         "netrom interface <interface> <alias> <quality>",
  85.     "irtt",        donrirtt,    0, 0,    NULLCHAR,
  86.     "kick",        donrkick,    0, 2,    "netrom kick <&nrcb>",
  87.     "nodefilter",    donodefilter,    0, 0,    NULLCHAR,
  88.     "nodetimer",    donodetimer,    0, 0,    NULLCHAR,
  89.     "obsotimer",    doobsotimer,    0, 0,    NULLCHAR,
  90.     "qlimit",    donrqlimit,    0, 0,    NULLCHAR,
  91.     "reset",    donrreset,    0, 2,    "netrom reset <&nrcb>",
  92.     "retries",    donrretries,    0, 0,    NULLCHAR,
  93.     "route",    donrroute,    0, 0,    NULLCHAR,
  94.     "status",    donrstatus,    0, 0,    NULLCHAR,
  95.     "timertype",    donrtype,    0, 0,    NULLCHAR,
  96.     "ttl",        donrttl,    0, 0,    NULLCHAR,
  97.     "user",        donruser,    0, 0,    NULLCHAR,
  98.     "verbose",    donrverbose,    0, 0,    NULLCHAR,
  99.     "window",    donrwindow,    0, 0,    NULLCHAR,
  100.     NULLCHAR,
  101. } ;
  102.  
  103. static struct timer Nodetimer ;    /* timer for nodes broadcasts */
  104. static struct timer Obsotimer ;    /* timer for aging routes */
  105.  
  106. /* Command multiplexer */
  107. int donetrom(argc,argv,p)
  108. int argc ;
  109. char *argv[] ;
  110. void *p;
  111. {
  112.     if(argc == 1)
  113.         return donrroute(argc,argv,p);
  114.     return subcmd(Nrcmds,argc,argv,p) ;
  115. }
  116.  
  117. static struct cmds Routecmds[] = {
  118.     "add",    dorouteadd,    0, 6,
  119.         "netrom route add <alias> <destination> <interface> <quality> <neighbor>",
  120.     "drop",    doroutedrop, 0, 4,
  121.         "netrom route drop <destination> <neighbor> <interface>",
  122.     "info", dorouteinfo, 0, 2,
  123.         "netrom route info <destination>",
  124.     NULLCHAR,
  125. } ;
  126.  
  127. /* Route command multiplexer */
  128. static int donrroute(argc, argv,p)
  129. int argc ;
  130. char *argv[] ;
  131. void *p;
  132. {
  133.     if (argc < 2) {
  134.         doroutedump() ;
  135.         return 0 ;
  136.     }
  137.     return subcmd(Routecmds,argc,argv,p) ;
  138. }
  139.  
  140. /* Dump a list of known routes */
  141. int doroutedump()
  142. {
  143.     register struct nrroute_tab *rp ;
  144.     register int i, column ;
  145.     char buf[16] ;
  146.     char *cp ;
  147.     
  148.     column = 1 ;
  149.     
  150.     for (i = 0 ; i < NRNUMCHAINS ; i++)
  151.         for (rp = Nrroute_tab[i] ; rp != NULLNRRTAB ; rp = rp->next) {
  152.             strcpy(buf,rp->alias) ;
  153.             /* remove trailing spaces */
  154.             if ((cp = strchr(buf,' ')) == NULLCHAR)
  155.                 cp = &buf[strlen(buf)] ;
  156.             if (cp != buf)        /* don't include colon for null alias */
  157.                 *cp++ = ':' ;
  158.             pax25(cp,rp->call) ;
  159.             tprintf("%-16s  ",buf) ;
  160.             if (column++ == 4) {
  161.                 if(tprintf("\n") == EOF)
  162.                     return 0;
  163.                 column = 1 ;
  164.             }
  165.         }
  166.  
  167.     if (column != 1)
  168.         tprintf("\n") ;
  169.         
  170.     return 0 ;
  171. }
  172.  
  173. /* print detailed information on an individual route */
  174. int dorouteinfo(argc,argv,p)
  175. int argc ;
  176. char *argv[] ;
  177. void *p;
  178. {
  179.     register struct nrroute_tab *rp ;
  180.     register struct nr_bind *bp ;
  181.     register struct nrnbr_tab *np ;
  182.     char dest[AXALEN] ;
  183.     char neighbor[AXBUF] ;
  184.  
  185.     if (setcall(dest,argv[1]) == -1) {
  186.         tprintf ("bad destination name\n") ;
  187.         return -1 ;
  188.     }
  189.         
  190.     if ((rp = find_nrroute(dest)) == NULLNRRTAB) {
  191.         tprintf("no such route\n") ;
  192.         return -1 ;
  193.     }
  194.  
  195.     for (bp = rp->routes ; bp != NULLNRBIND ; bp = bp->next) {
  196.         np = bp->via ;
  197.         if(tprintf("%1s %3d  %3d  %-8s  %s\n",
  198.          (bp->flags & NRB_PERMANENT ? "P" :
  199.          bp->flags & NRB_RECORDED ? "R" : " "),
  200.          bp->quality,bp->obsocnt,
  201.          Nrifaces[np->iface].iface->name,
  202.          pax25(neighbor,np->call)) == EOF)
  203.             break;
  204.     }
  205.     return 0 ;
  206. }
  207.  
  208. /* convert a null-terminated alias name to a blank-filled, upcased */
  209. /* version.  Return -1 on failure. */
  210. int putalias(to,from,complain)
  211. register char *to, *from ;
  212. int complain ;    
  213. {
  214.     int len, i ;
  215.     
  216.     if ((len = strlen(from)) > ALEN) {
  217.         if (complain)
  218.             tprintf ("alias too long - six characters max\n") ;
  219.         return -1 ;
  220.     }
  221.     
  222.     for (i = 0 ; i < ALEN ; *to++, *from++, i++) 
  223.         if (i < len) 
  224.             *to = toupper(*from) ;
  225.         else
  226.             *to = ' ' ;
  227.  
  228.     *to = '\0' ;
  229.     return 0 ;
  230. }
  231.  
  232. /* Add a route */
  233. static int dorouteadd(argc, argv,p)
  234. int argc ;
  235. char *argv[] ;
  236. void *p;
  237. {
  238.     char alias[AXALEN] ;
  239.     char dest[AXALEN] ;
  240.     unsigned quality ;
  241.     char neighbor[AXALEN] ;
  242.     register int i ;
  243.     int naddr ;
  244.  
  245.     /* format alias (putalias prints error message if necessary) */
  246.     if (putalias(alias,argv[1],1) == -1)
  247.         return -1 ;
  248.  
  249.     /* format destination callsign */
  250.     if (setcall(dest,argv[2]) == -1) {
  251.         tprintf("bad destination callsign\n") ;
  252.         return -1 ;
  253.     }
  254.  
  255.     /* find interface */
  256.     for (i = 0 ; i < Nr_numiface ; i++)
  257.         if (!strcmp(Nrifaces[i].iface->name,argv[3]))
  258.             break ;
  259.     if (i == Nr_numiface) {
  260.         tprintf("Interface \"%s\" not found\n",argv[3]) ;
  261.         return -1 ;
  262.     }
  263.     
  264.     /* get and check quality value */
  265.     if ((quality = atoi(argv[4])) > 255) {
  266.         tprintf("maximum route quality is 255\n") ;
  267.         return -1 ;
  268.     }
  269.  
  270.     /* Change from 871225 -- no digis in net/rom table */
  271.     naddr = argc - 5 ;
  272.     if (naddr > 1) {
  273.         tprintf("Use the ax25 route command to specify digipeaters\n") ;
  274.         return -1 ;
  275.     }
  276.     
  277.     /* format neighbor address string */
  278.     setcall(neighbor,argv[5]) ;
  279.  
  280.     return nr_routeadd(alias,dest,i,quality,neighbor,1,0) ;
  281. }
  282.  
  283.  
  284. /* drop a route */
  285. static int doroutedrop(argc,argv,p)
  286. int argc ;
  287. char *argv[] ;
  288. void *p;
  289. {
  290.     char dest[AXALEN], neighbor[AXALEN] ;
  291.     register int i ;
  292.  
  293.     /* format destination and neighbor callsigns */
  294.     if (setcall(dest,argv[1]) == -1) {
  295.         tprintf("bad destination callsign\n") ;
  296.         return -1 ;
  297.     }
  298.     if (setcall(neighbor,argv[2]) == -1) {
  299.         tprintf("bad neighbor callsign\n") ;
  300.         return -1 ;
  301.     }
  302.  
  303.     /* find interface */
  304.     for (i = 0 ; i < Nr_numiface ; i++)
  305.         if (!strcmp(Nrifaces[i].iface->name,argv[3]))
  306.             break ;
  307.     if (i == Nr_numiface) {
  308.         tprintf("Interface \"%s\" not found\n",argv[3]) ;
  309.         return -1 ;
  310.     }
  311.  
  312.     return nr_routedrop(dest,neighbor,i) ;
  313. }
  314.     
  315.     
  316. /* make an interface available to net/rom */
  317. static int dointerface(argc,argv,p)
  318. int argc ;
  319. char *argv[] ;
  320. void *p;
  321. {
  322.     int i ;
  323.     register struct iface *ifp ;
  324.  
  325.     if (Nr_iface == NULLIF) {
  326.         tprintf("Attach netrom interface first\n") ;
  327.         return 1 ;
  328.     }
  329.     
  330.     if (Nr_numiface >= NRNUMIFACE) {
  331.         tprintf("Only %d net/rom interfaces available\n",NRNUMIFACE) ;
  332.         return 1 ;
  333.     }
  334.     
  335.     if((ifp = if_lookup(argv[1])) == NULLIF){
  336.         tprintf(Badinterface,argv[1]);
  337.         return 1;
  338.     }
  339.     for (i = 0 ; i < Nr_numiface ; i++)
  340.         if (Nrifaces[i].iface == ifp) {
  341.             tprintf("Interface \"%s\" is already registered\n",argv[1]) ;
  342.             return 1 ;
  343.         }
  344.         
  345.     Nrifaces[Nr_numiface].iface = ifp ;
  346.  
  347.     if (putalias(Nrifaces[Nr_numiface].alias,argv[2],1) == -1)
  348.         return 1 ;
  349.         
  350.     if ((Nrifaces[Nr_numiface].quality = atoi(argv[3])) > 255) {
  351.         tprintf("Quality cannot be greater than 255\n") ;
  352.         return 1 ;
  353.     }
  354.         
  355.     Nr_numiface++ ;            /* accept this interface */
  356.     return 0 ;
  357. }
  358.  
  359. /* Broadcast nodes list on named interface. */
  360. static int dobcnodes(argc,argv,p)
  361. int argc ;
  362. char *argv[] ;
  363. void *p;
  364. {
  365.     register int i ;
  366.  
  367.     for (i = 0 ; i < Nr_numiface ; i++)
  368.         if (!strcmp(Nrifaces[i].iface->name,argv[1]))
  369.             break ;
  370.     if (i == Nr_numiface) {
  371.         tprintf("Interface \"%s\" not found\n",argv[1]) ;
  372.         return 1 ;
  373.     }
  374.         
  375.     nr_bcnodes(i) ;
  376.     return 0;
  377. }
  378.  
  379. #define TICKSPERSEC    (1000L / MSPTICK)    /* Ticks per second */
  380.  
  381. /* Set outbound node broadcast interval */
  382. static int donodetimer(argc,argv,p)
  383. int argc;
  384. char *argv[];
  385. void *p;
  386. {
  387.     if(argc < 2){
  388.         tprintf("Nodetimer %lu/%lu seconds\n",
  389.             read_timer(&Nodetimer)/TICKSPERSEC,
  390.             dur_timer(&Nodetimer)/TICKSPERSEC);
  391.         return 0;
  392.     }
  393.     stop_timer(&Nodetimer) ;    /* in case it's already running */
  394.     Nodetimer.func = (void (*)())donodetick;/* what to call on timeout */
  395.     Nodetimer.arg = NULLCHAR;        /* dummy value */
  396.     Nodetimer.start = atoi(argv[1])*TICKSPERSEC;    /* set timer duration */
  397.     start_timer(&Nodetimer);        /* and fire it up */
  398.     return 0;
  399. }
  400.  
  401. static void donodetick()
  402. {
  403.     register int i ;
  404.  
  405.     for (i = 0 ; i < Nr_numiface ; i++)
  406.         nr_bcnodes(i) ;
  407.  
  408.     /* Restart timer */
  409.     start_timer(&Nodetimer) ;
  410. }
  411.  
  412. /* Set timer for aging routes */
  413. static int doobsotimer(argc,argv,p)
  414. int argc;
  415. char *argv[];
  416. void *p;
  417. {
  418.     if(argc < 2){
  419.         tprintf("Obsotimer %lu/%lu seconds\n",
  420.             read_timer(&Obsotimer)/TICKSPERSEC,
  421.             dur_timer(&Obsotimer)/TICKSPERSEC);
  422.         return 0;
  423.     }
  424.     stop_timer(&Obsotimer) ;    /* just in case it's already running */
  425.     Obsotimer.func = (void (*)())doobsotick;/* what to call on timeout */
  426.     Obsotimer.arg = NULLCHAR;        /* dummy value */
  427.     Obsotimer.start = atoi(argv[1])*TICKSPERSEC;    /* set timer duration */
  428.     start_timer(&Obsotimer);        /* and fire it up */
  429.     return 0;
  430. }
  431.  
  432.  
  433. /* Go through the routing table, reducing the obsolescence count of
  434.  * non-permanent routes, and purging them if the count reaches 0
  435.  */
  436. static void doobsotick()
  437. {
  438.     register struct nrnbr_tab *np ;
  439.     register struct nrroute_tab *rp, *rpnext ;
  440.     register struct nr_bind *bp, *bpnext ;
  441.     int i ;
  442.  
  443.     for (i = 0 ; i < NRNUMCHAINS ; i++) {
  444.         for (rp = Nrroute_tab[i] ; rp != NULLNRRTAB ; rp = rpnext) {
  445.             rpnext = rp->next ;     /* save in case we free this route */
  446.             for (bp = rp->routes ; bp != NULLNRBIND ; bp = bpnext) {
  447.                 bpnext = bp->next ;    /* in case we free this binding */
  448.                 if (bp->flags & NRB_PERMANENT)    /* don't age these */
  449.                     continue ;
  450.                 if (--bp->obsocnt == 0) {        /* time's up! */
  451.                     if (bp->next != NULLNRBIND)
  452.                         bp->next->prev = bp->prev ;
  453.                     if (bp->prev != NULLNRBIND)
  454.                         bp->prev->next = bp->next ;
  455.                     else
  456.                         rp->routes = bp->next ;
  457.                     rp->num_routes-- ;            /* one less binding */
  458.                     np = bp->via ;                /* find the neighbor */
  459.                     free((char *)bp) ;                /* now we can free the bind */
  460.                     /* Check to see if we can free the neighbor */
  461.                     if (--np->refcnt == 0) {
  462.                         if (np->next != NULLNTAB)
  463.                             np->next->prev = np->prev ;
  464.                         if (np->prev != NULLNTAB)
  465.                             np->prev->next = np->next ;
  466.                         else {
  467.                             Nrnbr_tab[nrhash(np->call)] = np->next ;
  468.                         }
  469.                         free((char *)np) ;    /* free the storage */
  470.                     }
  471.                 }
  472.             }
  473.             if (rp->num_routes == 0) {        /* did we free them all? */
  474.                 if (rp->next != NULLNRRTAB)
  475.                     rp->next->prev = rp->prev ;
  476.                 if (rp->prev != NULLNRRTAB)
  477.                     rp->prev->next = rp->next ;
  478.                 else
  479.                     Nrroute_tab[i] = rp->next ;
  480.  
  481.                 free((char *)rp) ;
  482.             }
  483.         }
  484.     }
  485.  
  486.     start_timer(&Obsotimer) ;
  487. }
  488.  
  489. static struct cmds Nfcmds[] = {
  490.     "add",    donfadd,    0, 3,
  491.         "netrom nodefilter add <neighbor> <interface>",
  492.     "drop",    donfdrop,    0, 3,
  493.         "netrom nodefilter drop <neighbor> <interface>",
  494.     "mode",    donfmode,    0, 0,    NULLCHAR,
  495.     NULLCHAR,    NULLFP,    0, 0,
  496.         "nodefilter subcommands: add drop mode",
  497. } ;
  498.  
  499. /* nodefilter command multiplexer */
  500. static int donodefilter(argc,argv,p)
  501. int argc ;
  502. char *argv[] ;
  503. void *p;
  504. {
  505.     if (argc < 2) {
  506.         donfdump() ;
  507.         return 0 ;
  508.     }
  509.     return subcmd(Nfcmds,argc,argv,p) ;
  510. }
  511.  
  512. /* display a list of <callsign,interface> pairs from the filter
  513.  * list.
  514.  */
  515. static int donfdump()
  516. {
  517.     int i, column = 1 ;
  518.     struct nrnf_tab *fp ;
  519.     char buf[16] ;
  520.  
  521.     for (i = 0 ; i < NRNUMCHAINS ; i++)
  522.         for (fp = Nrnf_tab[i] ; fp != NULLNRNFTAB ; fp = fp->next) {
  523.             pax25(buf,fp->neighbor) ;
  524.             tprintf("%-7s %-8s  ",
  525.              buf,Nrifaces[fp->iface].iface->name) ;
  526.             if (column++ == 4) {
  527.                 if(tprintf("\n") == EOF)
  528.                     return 0;
  529.                 column = 1 ;
  530.             }
  531.         }
  532.  
  533.     if (column != 1)
  534.         tprintf("\n") ;
  535.  
  536.     return 0 ;
  537. }
  538.  
  539. /* add an entry to the filter table */
  540. static int donfadd(argc,argv,p)
  541. int argc ;
  542. char *argv[] ;
  543. void *p;
  544. {
  545.     char neighbor[AXALEN] ;
  546.     register int i ;
  547.  
  548.     /* format callsign */
  549.     if (setcall(neighbor,argv[1]) == -1) {
  550.         tprintf("bad neighbor callsign\n") ;
  551.         return -1 ;
  552.     }
  553.  
  554.     /* find interface */
  555.     for (i = 0 ; i < Nr_numiface ; i++)
  556.         if (!strcmp(Nrifaces[i].iface->name,argv[2]))
  557.             break ;
  558.     if (i == Nr_numiface) {
  559.         tprintf("Interface \"%s\" not found\n",argv[2]) ;
  560.         return -1 ;
  561.     }
  562.  
  563.     return nr_nfadd(neighbor,i) ;
  564. }
  565.  
  566. /* drop an entry from the filter table */
  567. static int donfdrop(argc,argv,p)
  568. int argc ;
  569. char *argv[] ;
  570. void *p;
  571. {
  572.     char neighbor[AXALEN] ;
  573.     register int i ;
  574.  
  575.     /* format neighbor callsign */
  576.     if (setcall(neighbor,argv[1]) == -1) {
  577.         tprintf("bad neighbor callsign\n") ;
  578.         return -1 ;
  579.     }
  580.  
  581.     /* find interface */
  582.     for (i = 0 ; i < Nr_numiface ; i++)
  583.         if (!strcmp(Nrifaces[i].iface->name,argv[2]))
  584.             break ;
  585.     if (i == Nr_numiface) {
  586.         tprintf("Interface \"%s\" not found\n",argv[2]) ;
  587.         return -1 ;
  588.     }
  589.  
  590.     return nr_nfdrop(neighbor,i) ;
  591. }
  592.  
  593. /* nodefilter mode subcommand */
  594. static int donfmode(argc,argv,p)
  595. int argc ;
  596. char *argv[] ;
  597. void *p;
  598. {
  599.     if (argc < 2) {
  600.         tprintf("filter mode is ") ;
  601.         switch (Nr_nfmode) {
  602.             case NRNF_NOFILTER:
  603.                 tprintf("none\n") ;
  604.                 break ;
  605.             case NRNF_ACCEPT:
  606.                 tprintf("accept\n") ;
  607.                 break ;
  608.             case NRNF_REJECT:
  609.                 tprintf("reject\n") ;
  610.                 break ;
  611.             default:
  612.                 tprintf("some strange, unknown value\n") ;
  613.         }
  614.         return 0 ;
  615.     }
  616.     
  617.     switch (argv[1][0]) {
  618.         case 'n':
  619.         case 'N':
  620.             Nr_nfmode = NRNF_NOFILTER ;
  621.             break ;
  622.         case 'a':
  623.         case 'A':
  624.             Nr_nfmode = NRNF_ACCEPT ;
  625.             break ;
  626.         case 'r':
  627.         case 'R':
  628.             Nr_nfmode = NRNF_REJECT ;
  629.             break ;
  630.         default:
  631.             tprintf("modes are: none accept reject\n") ;
  632.             return -1 ;
  633.     }
  634.  
  635.     return 0 ;
  636. }
  637.  
  638. /* netrom network packet time-to-live initializer */
  639. static int donrttl(argc, argv,p)
  640. int argc ;
  641. char *argv[] ;
  642. void *p;
  643. {
  644.     return setshort(&Nr_ttl,"Time to live",argc,argv);
  645. }
  646.  
  647. /* verbose route broadcast */
  648. static int donrverbose(argc,argv,p)
  649. int argc ;
  650. char *argv[] ;
  651. void *p;
  652. {
  653.     return setbool(&Nr_verbose,"Verbose flag",argc,argv);
  654. }
  655.  
  656. static int donrautorec(argc,argv,p)
  657. int argc ;
  658. char *argv[] ;
  659. void *p;
  660. {
  661.     return setbool(&Nr_autorec,"NR-AutoRecord flag",argc,argv);
  662. }
  663.  
  664. /* Initiate a NET/ROM transport connection */
  665. static int donrconnect(argc,argv,p)
  666. int argc ;
  667. char *argv[] ;
  668. void *p;
  669. {
  670.     char *np ;
  671.     struct sockaddr_nr lsocket, fsocket;
  672.     char alias[AXBUF];
  673.     struct session *sp;
  674.     int split = 0;
  675.  
  676.     /* Get a session descriptor */
  677.     if ((sp = newsession(argv[1],NRSESSION,split)) == NULLSESSION) {
  678.         tprintf("Too many sessions\n") ;
  679.         freeargs(argc,argv);
  680.         return 1 ;
  681.     }
  682.  
  683.     if((sp->s = socket(AF_NETROM,SOCK_SEQPACKET,0)) == -1){
  684.         tprintf("Can't create socket\n");
  685.         freeargs(argc,argv);
  686.         keywait(NULLCHAR,1);
  687.         freesession(sp);
  688.         return 1;
  689.     }
  690.     lsocket.nr_family = AF_NETROM;
  691.     /* Set up our local username, bind would use Mycall instead */
  692.     memcpy(lsocket.nr_addr.user,Nr4user,AXALEN);
  693.     /* Putting anything else than Mycall here will not work */
  694.     memcpy(lsocket.nr_addr.node,Mycall,AXALEN);
  695.     bind(sp->s,(char *)&lsocket,sizeof(struct sockaddr_nr));
  696.  
  697.     /* See if the requested destination could be an alias, and */
  698.     /* find and use it if it is.  Otherwise assume it is an ax.25 */
  699.     /* address. */
  700.     
  701.     if (putalias(alias,argv[1],0) != -1 &&
  702.         (np = find_nralias(alias)) != NULLCHAR) {
  703.         memcpy(fsocket.nr_addr.user,np,AXALEN) ;
  704.         memcpy(fsocket.nr_addr.node,np,AXALEN) ;
  705.     } else {    /* parse ax25 callsign */
  706.         /* Only the user callsign of the remote station is never used by */
  707.         /* NET/ROM, but it is needed for the psocket() call. */
  708.         setcall(fsocket.nr_addr.user,argv[1]);
  709.         setcall(fsocket.nr_addr.node,argv[1]);
  710.     }
  711.     freeargs(argc,argv);
  712.     fsocket.nr_family = AF_NETROM;
  713.     pax25(alias,fsocket.nr_addr.node);
  714.  
  715.     if(Nr_autorec) 
  716.         if((sp->record = fopen(alias,APPEND_TEXT)) == NULLFILE)
  717.             tprintf("Can't open %s: %s\n",alias,sys_errlist[errno]);
  718.         else
  719.             sp->rfile = strdup(alias);
  720.  
  721.     return tel_connect(sp, (char *)&fsocket, sizeof(struct sockaddr_nr));
  722. }
  723.  
  724. #ifdef    MAILBOX
  725. int nr4start(argc,argv,p)
  726. int argc;
  727. char *argv[];
  728. void *p;
  729. {
  730.     int s,type;
  731.  
  732.     freeargs(argc,argv);
  733.     if (Nrsocket != -1)
  734.         return -1;
  735.  
  736.     psignal(Curproc,0);    /* Don't keep the parser waiting */
  737.     chname(Curproc,"NETROM listener");
  738.     Nrsocket = socket(AF_NETROM,SOCK_SEQPACKET,0);
  739.     /* bind() is done automatically */
  740.     if (listen(Nrsocket,1) == -1) {
  741.         close_s(Nrsocket);
  742.         Nrsocket = -1;
  743.         return -1;
  744.     }
  745.     for(;;){
  746.         if((s = accept(Nrsocket,NULLCHAR,NULLINT)) == -1)
  747.             break;    /* Service is shutting down */
  748.  
  749.         type = NRSESSION;
  750.         newproc("mbox",2048,mbx_incom,s,(void *)&type,NULL);
  751.     }
  752.     close_s(Nrsocket);
  753.     Nrsocket = -1;
  754.     return 0;
  755. }
  756.  
  757. int nr40(argc,argv,p)
  758. int argc;
  759. char *argv[];
  760. void *p;
  761. {
  762.     close_s(Nrsocket);
  763.     Nrsocket = -1;
  764.     return 0;
  765. }
  766. #endif    /* MAILBOX */
  767.  
  768. /* Reset a net/rom connection abruptly */
  769. static int donrreset(argc,argv,p)
  770. int argc;
  771. char *argv[];
  772. void *p;
  773. {
  774.     struct nr4cb *cb ;
  775.  
  776.     cb = (struct nr4cb *)htol(argv[1]);
  777.     if(!nr4valcb(cb)){
  778.         tprintf(Notval);
  779.         return 1;
  780.     }
  781.     reset_nr4(cb);
  782.     return 0;
  783. }
  784.  
  785. /* Force retransmission on a net/rom connection */
  786.  
  787. static int donrkick(argc,argv,p)
  788. int argc;
  789. char *argv[];
  790. void *p;
  791. {
  792.     struct nr4cb *cb ;
  793.  
  794.     cb = (struct nr4cb *)htol(argv[1]);
  795.  
  796.     if (kick_nr4(cb) == -1) {
  797.         tprintf(Notval);
  798.         return 1;
  799.     } else
  800.         return 0;
  801. }
  802.  
  803. /* netrom transport ACK delay timer */
  804. static int donracktime(argc, argv,p)
  805. int argc ;
  806. char *argv[] ;
  807. void *p;
  808. {
  809.     return setlong(&Nr4acktime,"Ack delay time (ms)",argc,argv);
  810. }
  811.  
  812. /* netrom transport choke timeout */
  813. static int donrchoketime(argc, argv,p)
  814. int argc ;
  815. char *argv[] ;
  816. void *p;
  817. {
  818.     return setlong(&Nr4choketime,"Choke timeout (ms)",argc,argv);
  819. }
  820.  
  821. /* netrom transport initial round trip time */
  822.  
  823. static int donrirtt(argc, argv,p)
  824. int argc ;
  825. char *argv[] ;
  826. void *p;
  827. {
  828.     return setlong(&Nr4irtt,"Initial RTT (ms)",argc,argv);
  829. }
  830.  
  831. /* netrom transport receive queue length limit.  This is the */
  832. /* threshhold at which we will CHOKE the sender. */
  833. static int donrqlimit(argc, argv,p)
  834. int argc ;
  835. char *argv[] ;
  836. void *p;
  837. {
  838.     return setshort(&Nr4qlimit,"Queue limit (bytes)",argc,argv);
  839. }
  840.  
  841. /* Display or change our NET/ROM username */
  842. static int donruser(argc,argv,p)
  843. int argc;
  844. char *argv[];
  845. void *p;
  846. {
  847.     char buf[AXBUF];
  848.  
  849.     if(argc < 2){
  850.         pax25(buf,Nr4user);
  851.         tprintf("%s\n",buf);
  852.         return 0;
  853.     }
  854.     if(setcall(Nr4user,argv[1]) == -1)
  855.         return -1;
  856.     Nr4user[ALEN] |= E;
  857.     return 0;
  858. }
  859.  
  860. /* netrom transport maximum window.  This is the largest send and */
  861. /* receive window we may negotiate */
  862. static int donrwindow(argc, argv,p)
  863. int argc ;
  864. char *argv[] ;
  865. void *p;
  866. {
  867.     return setshort(&Nr4window,"Window (frames)",argc,argv);
  868. }
  869.  
  870. /* netrom transport maximum retries.  This is used in connect and */
  871. /* disconnect attempts; I haven't decided what to do about actual */
  872. /* data retries yet. */
  873.  
  874. static int donrretries(argc, argv,p)
  875. int argc ;
  876. char *argv[] ;
  877. void *p;
  878. {
  879.     return setshort(&Nr4retries,"Retry limit",argc,argv);
  880. }
  881.  
  882. /* Display the status of NET/ROM connections */
  883.  
  884. static int donrstatus(argc, argv,p)
  885. int argc ;
  886. char *argv[] ;
  887. void *p;
  888. {
  889.     int i ;
  890.     struct nr4cb *cb ;
  891.     char luser[AXBUF], ruser[AXBUF], node[AXBUF] ;
  892.     
  893.     if (argc < 2) {
  894.         tprintf("     &CB Snd-W Snd-Q Rcv-Q     LUser      RUser @Node     State\n");
  895.         for (i = 0 ; i < NR4MAXCIRC ; i++) {
  896.             if ((cb = Nr4circuits[i].ccb) == NULLNR4CB)
  897.                 continue ;
  898.             pax25(luser,cb->local.user) ;
  899.             pax25(ruser,cb->remote.user) ;
  900.             pax25(node,cb->remote.node) ;
  901.             if(tprintf("%8lx   %3d %5d %5d %9s  %9s %-9s %s\n",
  902.              ptol(cb), cb->nbuffered, len_q(cb->txq),
  903.              len_p(cb->rxq), luser, ruser, node,
  904.              Nr4states[cb->state]) == EOF)
  905.                 break;
  906.         }
  907.         return 0 ;
  908.     }
  909.  
  910.     cb = (struct nr4cb *)htol(argv[1]) ;
  911.     if (!nr4valcb(cb)) {
  912.         tprintf(Notval) ;
  913.         return 1 ;
  914.     }
  915.  
  916.     donrdump(cb) ;
  917.     return 0 ;
  918. }
  919.  
  920. /* Dump one control block */
  921. void donrdump(cb)
  922. struct nr4cb *cb ;
  923. {
  924.     char luser[AXBUF], ruser[AXBUF], node[AXBUF] ;
  925.     unsigned seq ;
  926.     struct nr4txbuf *b ;
  927.     struct timer *t ;
  928.  
  929.     pax25(luser,cb->local.user) ;
  930.     pax25(ruser,cb->remote.user) ;
  931.     pax25(node,cb->remote.node) ;
  932.  
  933.     tprintf("Local: %s %d/%d Remote: %s @ %s %d/%d State: %s\n",
  934.            luser, cb->mynum, cb->myid, ruser, node,
  935.            cb->yournum, cb->yourid, Nr4states[cb->state]) ;
  936.  
  937.     tprintf("Window: %-5u Rxpect: %-5u RxNext: %-5u RxQ: %-5d %s\n",
  938.            cb->window, uchar(cb->rxpected), uchar(cb->rxpastwin),
  939.            len_p(cb->rxq), cb->qfull ? "RxCHOKED" : "") ;
  940.  
  941.     tprintf(" Unack: %-5u Txpect: %-5u TxNext: %-5u TxQ: %-5d %s\n",
  942.            cb->nbuffered, uchar(cb->ackxpected), uchar(cb->nextosend),
  943.            len_q(cb->txq), cb->choked ? "TxCHOKED" : "") ;
  944.  
  945.     tprintf("TACK: ") ;
  946.     if (run_timer(&cb->tack))
  947.         tprintf("%lu", read_timer(&cb->tack) * MSPTICK) ;
  948.     else
  949.         tprintf("stop") ;
  950.     tprintf("/%lu ms; ", dur_timer(&cb->tack) * MSPTICK) ;
  951.  
  952.     tprintf("TChoke: ") ;
  953.     if (run_timer(&cb->tchoke))
  954.         tprintf("%lu", read_timer(&cb->tchoke) * MSPTICK) ;
  955.     else
  956.         tprintf("stop") ;
  957.     tprintf("/%lu ms; ", dur_timer(&cb->tchoke) * MSPTICK) ;
  958.  
  959.     tprintf("TCD: ") ;
  960.     if (run_timer(&cb->tcd))
  961.         tprintf("%lu", read_timer(&cb->tcd) * MSPTICK) ;
  962.     else
  963.         tprintf("stop") ;
  964.     tprintf("/%lu ms", dur_timer(&cb->tcd) * MSPTICK) ;
  965.  
  966.     if (run_timer(&cb->tcd))
  967.         tprintf("; Tries: %u\n", cb->cdtries) ;
  968.     else
  969.         tprintf("\n") ;
  970.  
  971.     tprintf("Backoff Level %u SRTT %ld ms Mean dev %ld ms\n",
  972.            cb->blevel, cb->srtt, cb->mdev) ;
  973.  
  974.     /* If we are connected and the send window is open, display */
  975.     /* the status of all the buffers and their timers */
  976.     
  977.     if (cb->state == NR4STCON && cb->nextosend != cb->ackxpected) {
  978.  
  979.         tprintf("TxBuffers:  Seq  Size  Tries  Timer\n") ;
  980.  
  981.         for (seq = cb->ackxpected ;
  982.              nr4between(cb->ackxpected, seq, cb->nextosend) ;
  983.              seq = (seq + 1) & NR4SEQMASK) {
  984.  
  985.             b = &cb->txbufs[seq % cb->window] ;
  986.             t = &b->tretry ;
  987.  
  988.             if(tprintf("            %3u   %3d  %5d  %lu/%lu\n",
  989.              seq, len_p(b->data), b->retries + 1,
  990.              read_timer(t) * MSPTICK, dur_timer(t) * MSPTICK)
  991.              == EOF)
  992.                 break;
  993.         }
  994.  
  995.     }
  996.  
  997. }
  998.  
  999. /* netrom timers type - linear v exponential */
  1000. static donrtype(argc,argv,p)
  1001. int argc ;
  1002. char *argv[] ;
  1003. void *p ;
  1004. {
  1005.     extern unsigned Nr_timertype;
  1006.  
  1007.     if (argc < 2) {
  1008.         tprintf("Netrom timer type is %s\n", Nr_timertype ? "linear" : "exponential" ) ;
  1009.         return 0 ;
  1010.     }
  1011.     
  1012.     switch (argv[1][0]) {
  1013.         case 'l':
  1014.         case 'L':
  1015.             Nr_timertype = 1 ;
  1016.             break ;
  1017.         case 'e':
  1018.         case 'E':
  1019.             Nr_timertype = 0 ;
  1020.             break ;
  1021.         default:
  1022.             tprintf("use: netrom timertype [linear|exponential]\n") ;
  1023.             return -1 ;
  1024.     }
  1025.  
  1026.     return 0 ;
  1027. }
  1028.  
  1029.